package org.example.compare.schedule;


import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import io.micrometer.common.util.StringUtils;
import org.example.compare.dto.*;
import org.example.compare.global.SchData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

import static org.example.compare.global.Global.*;

@Component
public class SchProcessPosition {
    @Autowired
    PreScheduling preScheduling;

    @Autowired
    CSchDataCollector cSchDataCollector;

    public static int Version;//数据版本，与数据库不同则重新获取数据
    public static Map<Long, OrderProcess> hProcessSet = new HashMap<>();//需要进行排产的工序集
    public static Set<Long> sPositionsCanSend = new HashSet<>();//可以发送的工位
    public static Set<Long> sPositionsScore = new HashSet<>();//可以排产的工位
    public static Map<Long, SBoxData> hBoxes = new HashMap<>();//可用的筐
    public static Map<Long, List<Score>> hScoreByProcess = new HashMap<>();//按工序查找的分数表，可以对hScoreByProcess进行降序排序
    public static Map<Long, List<Score>> hScoreByPosition = new HashMap<>();//按工位查找的分数表，可以对不同工序进行排序
    public static List<Score> scores = new ArrayList<>();//分数的保持者，前面两个只是为了方便查找和排序，建构和保存和析构以这个为准

    private void calculateScore() {
        float fb = 0.0f;
        SysParam schPower_lastNBox = SchData.hParamSet.get("SchPower_LastNBox");
        if (schPower_lastNBox != null && schPower_lastNBox.getEffective()) {
            fb = Float.parseFloat(schPower_lastNBox.getParamDefaultValue());
            calculateItem_1(fb / 100.0);
        }

        SysParam schPower_deadLine = SchData.hParamSet.get("SchPower_DeadLine");
        if (schPower_deadLine != null && schPower_deadLine.getEffective()) {
            fb = Float.parseFloat(schPower_deadLine.getParamDefaultValue());
            calculateItem_2(fb / 100.0);
        }

        SysParam schPower_efficiency = SchData.hParamSet.get("SchPower_Efficiency");
        if (schPower_efficiency != null && schPower_efficiency.getEffective()) {
            fb = Float.parseFloat(schPower_efficiency.getParamDefaultValue());
            calculateItem_3(fb / 100.0);
        }

        SysParam schPower_processChange = SchData.hParamSet.get("SchPower_ProcessChange");
        if (schPower_processChange != null && schPower_processChange.getEffective()) {
            fb = Float.parseFloat(schPower_processChange.getParamDefaultValue());
            calculateItem_4(fb / 100.0);
        }

        SysParam schPower_processPrepare = SchData.hParamSet.get("SchPower_ProcessPrepare");
        if (schPower_processPrepare != null && schPower_processPrepare.getEffective()) {
            fb = Float.parseFloat(schPower_processPrepare.getParamDefaultValue());
            calculateItem_5(fb / 100.0);
        }

        SysParam schPower_processBoxful = SchData.hParamSet.get("SchPower_ProcessBoxful");
        if (schPower_processBoxful != null && schPower_processBoxful.getEffective()) {
            fb = Float.parseFloat(schPower_processBoxful.getParamDefaultValue());
            calculateItem_6(fb / 100.0);
        }

        calculateItem_7(1.0);

        SysParam schPower_posFree = SchData.hParamSet.get("SchPower_PosFree");
        if (schPower_posFree != null && schPower_posFree.getEffective()) {
            fb = Float.parseFloat(schPower_posFree.getParamDefaultValue());
            calculateItem_8(fb / 100.0);
        }

        SysParam schPower_addPos = SchData.hParamSet.get("SchPower_AddPos");
        if (schPower_addPos != null) {
            fb = Float.parseFloat(schPower_addPos.getParamDefaultValue());
            calculateItem_9(fb / 100.0, schPower_addPos.getEffective());
        }

        SysParam schPower_machineType = SchData.hParamSet.get("SchPower_MachineType");
        if (schPower_machineType != null && schPower_machineType.getEffective()) {
            fb = Float.parseFloat(schPower_machineType.getParamDefaultValue());
            calculateItem_12(fb / 100.0);
        }

        SysParam schPower_doneInOrder = SchData.hParamSet.get("SchPower_DoneInOrder");
        if (schPower_doneInOrder != null && schPower_doneInOrder.getEffective()) {
            fb = Float.parseFloat(schPower_doneInOrder.getParamDefaultValue());
            calculateItem_13(fb / 100.0);
        }

        SysParam processTypeRate = SchData.hParamSet.get("schPower_processTypeRate");
        if (processTypeRate != null && processTypeRate.getEffective()) {
            fb = Float.parseFloat(processTypeRate.getParamDefaultValue());
            calculateItem_14(fb / 100.0);
        }

        calculateItem_10(); //黑名单
    }

    private boolean faKuang_MinSTD(Score s) {
        if (SchData.pPositionDtos.get(s.getPositionId()).getMiPosStatus() == FREE_P_S) {
            return true;
        }
        if (!reCheckCanSend_MinSTD(s)) {
            return false;
        }
//        if (!recheckCanSend_QieHuan(s)) {
//            log.info(String.format("不发出工序,（订单%s（%s），部件%s，简称%s（%s））给工位Id%s,原因%s",
//                    s.getPOp().getMLocalOrderNum(), s.getPOp().getMOuterOrderNum(), s.getPOp().getMPartId(),
//                    s.getPOp().getMProcessBrief(), s.getPOp().getMiPartSeqNum(), s.getPositionId(), s.getRemark()));
//            return false;
//        }
        if (!recheckCanSend_WeiChi(s)) {
            return false;
        }
        if ((isAllUndoInLibAndFew(s.getPOp().getOrderProcessId())) && (!recheckCanSend_QuanBuZaiKu(s))) {
            return false;
        }

        return true;
    }

    private void calculateItem_1(double ratio) {
        if (ratio < 0.01) return;
        int gRuleMinBoxInLib = Integer.parseInt(SchData.hParamSet.get("MinInLibBoxPer").getParamDefaultValue());
        int gRuleMinStdtimeInLib = Integer.parseInt(SchData.hParamSet.get("MinInLibSTDPer").getParamDefaultValue());

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if(pOp.getMScheduling() == null) {
                continue;
            }
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            //int inLibOrWorking = pOp.getMScheduling().getMBoxesInLib().getMiCutCnt() + pOp.getMScheduling().getMBoxesInWork().getMiCutCnt();
            if (!pOp.getMScheduling().isMbAllUnDoInLib()) {
                continue;
            }
            double fb = 10.0;
            float totalInlibSecond = pOp.getMfProcessTotalTime();
            totalInlibSecond *= pOp.getMScheduling().getMBoxesInLib().getMiCutCnt();
            if (pOp.getMScheduling().getMBoxesInLib().getMiBoxCnt() <= gRuleMinBoxInLib) {
                fb += 10.0;
            }
            if (totalInlibSecond <= gRuleMinStdtimeInLib) {
                fb += 10.0;
            }
            fb *= ratio;
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScor : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScor.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScor.getPositionId())) {
                    pScor.getScoreItem()[0] = fb;
                    pScor.setTotal(pScor.getTotal() + fb);
                }
            }
        }
    }

    private void calculateItem_2(double ratio) {
        if (ratio < 0.01) return;
        double dMax = 0;
        double dMin = 10000000.0;
        int iNormalHour = Integer.parseInt(SchData.hParamSet.get("NormalPeriodHour").getParamDefaultValue());
        if (iNormalHour == 0) iNormalHour = 1;

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }

            double fb = pOp.getMScheduling().getMNowHourTarget();
            if (fb == 0) {
                fb = 1.0;
            }

            double dLeftHour = 0;
            OrderDto order = SchData.orderId2Order.get(pOp.getMLocalOrderNum());
            dLeftHour = order.getMiNow2DeadlineSecs();
            dLeftHour /= 3600.0;

            dLeftHour /= iNormalHour;
            fb *= Math.exp(-dLeftHour);
            if (fb > dMax) dMax = fb;
            if (fb < dMin) dMin = fb;
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    pScore.getScoreItem()[1] = fb;// *ratio;
                }
            }
        }

        //归一化
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    double fb = pScore.getScoreItem()[1];
                    double fb1 = 10.0;
                    if (dMax > dMin) {
                        fb1 = ((fb - dMin) / (dMax - dMin) * 9.0 + 1.0) * ratio;
                    } else
                        fb1 = fb > 0 ? 10.0 * ratio : 0.0;
                    pScore.getScoreItem()[1] = fb1 > 0 ? fb1 : 0.0;// *ratio;
                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[1]);
                }
            }
        }
    }

    private void calculateItem_3(double ratio) {
        if (ratio < 0.01) return;
        double dMax = 0;
        double dMin = 10000000.0;

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    for (WorkerTech rate : SchData.hRate.get(pOp.getProcessId())) {
                        if (SchData.pPositionDtos.get(pScore.getPositionId()).getWorkerId() == rate.getWorkerId()) {
                            if (rate.getAvgProcessRate() > dMax) dMax = rate.getAvgProcessRate();
                            if (rate.getAvgProcessRate() < dMin) dMin = rate.getAvgProcessRate();
                            pScore.getScoreItem()[2] = rate.getAvgProcessRate();
                            break;
                        }
                    }
                }
            }
        }

        //归一化,需要在不同工序内归一化，才能反映一个工人最适合做什么
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    double fb = pScore.getScoreItem()[2];
                    double fb1 = 10.0 * ratio;
                    if (Math.abs(dMax - dMin) > 0.01) {
                        fb1 = ((fb - dMin) / (dMax - dMin) * 9.0 + 1.0) * ratio;
                    } else {
                        fb1 = fb > 0 ? 10.0 * ratio : 0;
                    }
                    pScore.getScoreItem()[2] = fb1 > 0 ? fb1 : 0.0;
                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[2]);
                }
            }
        }
    }

    private void calculateItem_4(double ratio) {
        if (ratio < 0.01) return;

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    if (pOp.getMScheduling().getMisWorkingPos().contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[3] = 10.0 * ratio;
                        pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[3]);
                    } else {
                        //找到工位当前工序
                        OrderProcess pOpTemp = preScheduling.getProcessWorkingByPosition(pScore.getPositionId());
                        if (pOpTemp == null) {
                            //没有当前工序不用做
                        } else {
                            //通过正在做的工序找当前订单
                            OrderDto order = SchData.orderId2Order.get(pOp.getMLocalOrderNum());
                            OrderDto tempOrder = SchData.orderId2Order.get(pOpTemp.getMLocalOrderNum());
                            if (order.getMLocalOrderNum().equals(tempOrder.getMLocalOrderNum())) {
                                pScore.getScoreItem()[3] = 6.0 * ratio;
                                pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[3]);
                            } else {
                                if (order.getMColor().equals(tempOrder.getMColor())) {
                                    pScore.getScoreItem()[3] = 5.0 * ratio;
                                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[3]);
                                } else if (order.getMLineColorNum().equals(tempOrder.getMLineColorNum())) {
                                    pScore.getScoreItem()[3] = 5.0 * ratio;
                                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[3]);
                                } else if (order.getMOuterOrderNum().equals(tempOrder.getMOuterOrderNum())) {
                                    pScore.getScoreItem()[3] = 4.0 * ratio;
                                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[3]);
                                } else if (pOp.getMProcessType().equals(pOpTemp.getMProcessType()) && pOp.getMProcessType().length() > 0) {
                                    pScore.getScoreItem()[3] = 2.0 * ratio;
                                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[3]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private void calculateItem_5(double ratio) {
        if (ratio < 0.01) return;
        double dMax = -10000000000.0;
        double dMin = 10000000000.0;
        int iSTD = Integer.parseInt(SchData.hParamSet.get("MinInLibSTDPer").getParamDefaultValue());

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            double fbInProcess = 0.0;
            //当前工序在产人数
            int workingPosCNT = pOp.getMScheduling().getMisWorkingPos().size();
            //依赖该工序的工序的总在库件总工时
            double dbNextProcInLib = 0.0;
            //依赖该工序的工序的总在产人数
            int iNextProcPos = 0;
            OrderDto order = SchData.orderId2Order.get(pOp.getMLocalOrderNum());
            Map<Integer, OrderProcess> processMap = order.getMOrderProcessSetGroupByPart().getOrDefault(pOp.getMPartId(), new TreeMap<>());
            Set<OrderProcess> preProcessSet = preScheduling.findAfterProcess(processMap.values(), pOp);
            for (OrderProcess nextProcess : preProcessSet) {
                if (preScheduling.isOutLine(nextProcess) ||
                        preScheduling.isInterrupt(nextProcess) ||
                        preScheduling.isSecondPackup(nextProcess) ||
                        preScheduling.isSendOut(nextProcess)) {
                    fbInProcess = NIL;
                    break;
                }
                //int inLibOrWorking = nextProcess->mScheduling->miInLibBoxCnt + pOp->mScheduling->mWorkingBoxID.count();
                int workingPosCntNextProcess = nextProcess.getMScheduling().getMisWorkingPos().size();
                //在库件数
                double dbf1 = nextProcess.getMScheduling() != null ? nextProcess.getMScheduling().getMBoxesInLib().getMiCutCnt() : 0.0;
                dbf1 *= nextProcess.getMfProcessTotalTime();
                dbNextProcInLib += dbf1;
                if (workingPosCntNextProcess == 0) {//如果没有人在做，系统希望有一个人在做
                    workingPosCntNextProcess = 1;
                }
                iNextProcPos += workingPosCntNextProcess;
            }

            if (fbInProcess != NIL) {
                //int iSTD = 0;
                //当前工序在产工时
                double dbf2 = iNextProcPos * iSTD;
                //依赖该工序的工序的总在产工时
                double dbf3 = workingPosCNT * iSTD;
                fbInProcess = dbf2 - dbNextProcInLib - dbf3;

                if (dMax < fbInProcess) {
                    dMax = fbInProcess;
                }
                if (dMin > fbInProcess) {
                    dMin = fbInProcess;
                }
                if (hScoreByProcess.get(iter.getKey()) == null) continue;
                for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                    if (!sPositionsScore.contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[4] = NIL;
                        continue;
                    }
                    if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[4] = fbInProcess;
                    }
                }
            } else {
                if (hScoreByProcess.get(iter.getKey()) == null) continue;
                for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                    if (!sPositionsScore.contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[4] = NIL;
                        continue;
                    }
                    if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[4] = 20.0;
                    }
                }
            }
        }

        //归一化,需要在不同工序内归一化，才能反映一个工人最适合做什么
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    pScore.getScoreItem()[4] = 0.0;
                    continue;
                }
                if (pScore.getScoreItem()[4] == NIL) {
                    pScore.getScoreItem()[4] = 0.0;
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    if (pScore.getScoreItem()[4] == NIL) {
                        pScore.getScoreItem()[4] = 0.0;
                        continue;
                    }
                    if (pScore.getScoreItem()[4] != 20.0) {
                        double fb = pScore.getScoreItem()[4];
                        double fb1 = 10.0 * ratio;
                        if (Math.abs(dMax - dMin) > 0.01) {
                            fb1 = ((fb - dMin) / (dMax - dMin) * 9.0 + 1.0) * ratio;
                        }
                        pScore.getScoreItem()[4] = fb1 > 0 ? fb1 : 0.0;
                        pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[4]);
                    } else {
                        pScore.getScoreItem()[4] = 20.0 * ratio;
                        pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[4]);
                    }
                }
            }
        }
    }

    private void calculateItem_6(double ratio) {
        if (ratio < 0.01) return;
        int iSTD = 0;
        int iMinInLibBox = 0;
        iSTD = Integer.parseInt(SchData.hParamSet.get("MinInLibSTDPer").getParamDefaultValue());
        iMinInLibBox = Integer.parseInt(SchData.hParamSet.get("MinInLibBoxPer").getParamDefaultValue());

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }

            int workingPosCNT = pOp.getMScheduling().getMisWorkingPos().size();
            int inLibBox = pOp.getMScheduling().getMBoxesInLib().getMiBoxCnt();
            double dbf = pOp.getMScheduling() != null ? pOp.getMScheduling().getMBoxesInLib().getMiCutCnt() : 0.0;
            dbf *= pOp.getMfProcessTotalTime();
            int inLibBoxPerPos = inLibBox;
            double dbf1 = dbf;
            if (workingPosCNT > 0) {
                inLibBoxPerPos /= workingPosCNT;
                dbf1 /= workingPosCNT;
            }

            int iScore = 0;
            if ((inLibBoxPerPos >= iMinInLibBox) && (dbf1 >= iSTD)) {
                iScore = 10;
            } else if (dbf1 >= iSTD) {
                iScore = 8;
            } else if (dbf >= iSTD) {
                iScore = 5;
            } else if (inLibBox >= iMinInLibBox) {
                iScore = 2;
            }

            double dbf2 = iScore;
            dbf2 *= ratio;
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    if (Math.abs(pScore.getScoreItem()[5] - 20.0) > 0.001) {
                        pScore.getScoreItem()[5] = dbf2;
                    } else {
                        pScore.getScoreItem()[5] *= ratio;
                    }
                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[5]);
                }
            }
        }
    }

    private void calculateItem_7(double ratio) {
        if (ratio < 0.01) return;

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            OrderDto orderDto = SchData.orderId2Order.get(pOp.getMLocalOrderNum());

            if (pOp.getMScheduling().isMbUrgentFlag() || (orderDto != null && orderDto.mbPriFlag)) {
                //dbf *= ratio;
                if (hScoreByProcess.get(iter.getKey()) == null) continue;
                for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                    if (!sPositionsScore.contains(pScore.getPositionId())) {
                        continue;
                    }
                    if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                        if (StrUtil.isNotBlank(pOp.getMScheduling().getMbUrgentCode())) {
                            // 根据加急等级获取分数
                            pScore.getScoreItem()[6] = SchData.processUrgentLevels.getOrDefault(pOp.getMScheduling().getMbUrgentCode(), INSERT_TICKET);
                        } else {
                            // 默认加急分数
                            pScore.getScoreItem()[6] = INSERT_TICKET;
                        }
                        pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[6]);
                    }
                }
            }
        }
    }

    private void calculateItem_8(double ratio) {
        if (ratio < 0.01) return;

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    double dbf = 0.0;
                    if (SchData.pPositionDtos.get(pScore.getPositionId()).getMiPosStatus() == FREE_P_S) {
                        dbf = 20.0;
                    } else {
                        OrderProcess pOpTemp = preScheduling.getProcessWorkingByPosition(pScore.getPositionId());
                        int inLibCNT = 0;
                        if ((pOpTemp != null) && (pOpTemp.getProcessId() != pOp.getProcessId())) {
                            inLibCNT = pOpTemp.getMScheduling() != null ? pOpTemp.getMScheduling().getMBoxesInLib().getMiBoxCnt() : 0;
                        }
                        if (pOpTemp == null) {
                            dbf = 10.0;
                        } else if (pOpTemp.getProcessId() == pOp.getProcessId()) {
                            dbf = 10.0;
                        } else if (inLibCNT > 0) {
                            dbf = 0.0;
                        } else if (SchData.pPositionDtos.get(pScore.getPositionId()).getMiPosStatus() == IN_PRO_ONLY_P_S) {
                            dbf = 8.0;
                        } else if (SchData.pPositionDtos.get(pScore.getPositionId()).getMiPosStatus() == WAITING_FOR_ONLY_PRO_P_S) {
                            dbf = 3.0;
                        } else if (SchData.pPositionDtos.get(pScore.getPositionId()).getMiPosStatus() == IN_THE_WAY_P_S) {
                            dbf = 2.0;
                        } else if (SchData.pPositionDtos.get(pScore.getPositionId()).getMiPosStatus() == BUSY_P_S) {
                            dbf = 1.0;
                        }
                    }
                    pScore.getScoreItem()[7] = dbf * ratio;
                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[7]);
                }
            }
        }
    }

    private void calculateItem_9(double ratio, Boolean effective) {
        //用实际的小时任务数成衣每件标准工时，得到当前的小时需要多少标准工时
        double dbOnHour = 0.0;
        double dbWorkerHour = 0.0;
        double dMax = 0.0;
        double dMin = 0.0;
        float baseTime = BASE_TIME;

        SysParam addPosBaseTime = SchData.hParamSet.get("AddPosBaseTime");
        if (addPosBaseTime != null) {
            baseTime = Float.parseFloat(addPosBaseTime.getParamDefaultValue());
        }

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }

            pOp.getMScheduling().setMIncDecFlag(0);
            dbOnHour = pOp.getMfProcessTotalTime() * pOp.getMScheduling().getMNowHourTarget();
            dbWorkerHour = 0.0;
            for (long iPos : pOp.getMScheduling().getMisWorkingPos()) {
                if (!SchData.pPositionDtos.containsKey(iPos)) {
                    continue;
                }
                if (AGENT_WORKER_NUM.equals(SchData.pPositionDtos.get(iPos).getMiWorkerNum())) {
                    dbWorkerHour += baseTime;
                    continue;
                }
                if (!SchData.hRate.containsKey(pOp.getProcessId())) {
                    dbWorkerHour += baseTime;
                    continue;
                }
                double posRate = baseTime;
                for (WorkerTech r : SchData.hRate.get(pOp.getProcessId())) {
                    if (r.getWorkerId().equals(SchData.pPositionDtos.get(iPos).getWorkerId())) {
                        posRate = 2 * baseTime * r.getAvgProcessRate();
                    }
                }
                dbWorkerHour += posRate;
            }
            double dbDiff = dbOnHour - dbWorkerHour;
            if (dbDiff >= 0.0) {
                if (dbDiff > dMax) {
                    dMax = dbDiff;
                }
                if (hScoreByProcess.get(iter.getKey()) == null) continue;
                for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                    if (!sPositionsScore.contains(pScore.getPositionId())) {
                        continue;
                    }
                    if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[8] = dbDiff;
                    }
                }
                if (dbDiff > baseTime * 6) {
                    pOp.getMScheduling().setMIncDecFlag(6);
                } else if (dbDiff > baseTime * 5) {
                    pOp.getMScheduling().setMIncDecFlag(6);
                } else if (dbDiff > baseTime * 4) {
                    pOp.getMScheduling().setMIncDecFlag(5);
                } else if (dbDiff > baseTime * 3) {
                    pOp.getMScheduling().setMIncDecFlag(4);
                } else if (dbDiff > baseTime * 2) {
                    pOp.getMScheduling().setMIncDecFlag(3);
                } else if (dbDiff > baseTime * 1) {
                    pOp.getMScheduling().setMIncDecFlag(2);
                } else if (dbDiff > baseTime * 0.02) {
                    pOp.getMScheduling().setMIncDecFlag(1);
                } else if (pOp.getMScheduling().getMisWorkingPos().isEmpty()) {
                    pOp.getMScheduling().setMIncDecFlag(1);
                }
            } else if (dbDiff < -0.0) {
                if (dbDiff < dMin) {
                    dMin = dbDiff;
                }
                if (hScoreByProcess.get(iter.getKey()) == null) continue;
                for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                    if (!sPositionsScore.contains(pScore.getPositionId())) {
                        continue;
                    }
                    if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[8] = dbDiff;
                    }
                }
                if (dbDiff < -3600.0) {
                    pOp.getMScheduling().setMIncDecFlag(-1);
                }
            }
        }
        //进行归一化并处理工位不同状态的系数关系
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    if (pScore.getScoreItem()[8] > 0) {
                        pScore.getScoreItem()[8] = ((10.0 - gBalanceLevel) * pScore.getScoreItem()[8]) / dMax;
                        if (pOp.getMScheduling().getMisWorkingPos().contains(pScore.getPositionId())) {
                            pScore.getScoreItem()[8] *= 1.0;
                        } else if (pOp.getMScheduling().getMPlanPositions().contains(pScore.getPositionId())) {
                            pScore.getScoreItem()[8] *= 0.9;
                        } else if (pOp.getMScheduling().getMisHaveDonePos().contains(pScore.getPositionId())) {
                            pScore.getScoreItem()[8] *= 0.75;
                        } else {
                            pScore.getScoreItem()[8] *= 0.5;
                        }
                        pScore.getScoreItem()[8] += gBalanceLevel;
                    } else if (pScore.getScoreItem()[8] < 0) {
                        pScore.getScoreItem()[8] = (-gBalanceLevel * pScore.getScoreItem()[8]) / dMin;
                        if (pOp.getMScheduling().getMPlanPositions().contains(pScore.getPositionId())) {
                            pScore.getScoreItem()[8] *= 1.0;
                        } else if (pOp.getMScheduling().getMisWorkingPos().contains(pScore.getPositionId())) {
                            pScore.getScoreItem()[8] *= 0.8;
                        } else {
                            pScore.getScoreItem()[8] *= 0.7;
                        }
                        pScore.getScoreItem()[8] += gBalanceLevel;
                    } else {
                        pScore.getScoreItem()[8] = gBalanceLevel;
                    }

                    double fb = pScore.getScoreItem()[8];
                    double fb1 = fb * ratio;
                    pScore.getScoreItem()[8] = fb1 > 0 ? fb1 : 0.0;
                    if (effective) {
                        pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[8]);
                    }
                }
            }
        }
    }

    private void calculateItem_10() {
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMisBlackList().contains(pScore.getPositionId())) {
                    pScore.getScoreItem()[9] = -pScore.getTotal();
                    pScore.setTotal(0);
                }
            }
        }
    }

    private void calculateItem_12(double ratio) {
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    List<Long> mMachineTypes = SchData.pPositionDtos.get(pScore.getPositionId()).getMMachineTypeIds();
                    for (int i = 0; i < mMachineTypes.size(); i++) {
                        if (pOp.getMMachineTypeId().equals(mMachineTypes.get(i))) {
                            if (mMachineTypes.get(i) != null) {
                                //pScore.getScoreItem()[11] = 10.0 / MAX_POSITION_MACHINE_TYPE_NUM * (MAX_POSITION_MACHINE_TYPE_NUM - i) * ratio;
                                pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[11]);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    private void calculateItem_13(double ratio) {
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    if (pOp.getMScheduling().getMisHaveDonePos().contains(pScore.getPositionId())) {
                        pScore.getScoreItem()[12] = 10.0 * ratio;
                        pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[12]);
                    }
                }
            }
        }
    }

    private void calculateItem_14(double ratio) {
        if (ratio < 0.01) return;
        double dMax = 0;
        double dMin = 10000000.0;

        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    PositionDto positionDto = SchData.pPositionDtos.get(pScore.getPositionId());
                    if (positionDto == null) continue;

                    WorkerTechType rate = SchData.workerToTechType.get(Pair.of(positionDto.getWorkerId(), pOp.getMProcessType()));
                    if (rate != null && StringUtils.isNotEmpty(pOp.getMProcessType()) && pOp.getMProcessType().equals(rate.getProcessType()) && rate.getAvgProcessRate() != 0) {
                        if (rate.getAvgProcessRate() > dMax) dMax = rate.getAvgProcessRate();
                        if (rate.getAvgProcessRate() < dMin) dMin = rate.getAvgProcessRate();
                        pScore.getScoreItem()[15] = rate.getAvgProcessRate();
                    }
                }
            }
        }

        //归一化,需要在不同工序内归一化，才能反映一个工人最适合做什么
        for (Map.Entry<Long, OrderProcess> iter : hProcessSet.entrySet()) {
            OrderProcess pOp = iter.getValue();
            if (pOp.getMScheduling().isMbHoldFlag()) {
                continue;
            }
            if (pOp.getMScheduling().isMbNGFlag()) {
                continue;
            }
            if (hScoreByProcess.get(iter.getKey()) == null) continue;
            for (Score pScore : hScoreByProcess.get(iter.getKey())) {
                if (!sPositionsScore.contains(pScore.getPositionId())) {
                    continue;
                }
                if (pOp.getMScheduling().getMPosCanDo().contains(pScore.getPositionId())) {
                    double fb = pScore.getScoreItem()[15];
                    double fb1 = 0;
                    if (Math.abs(dMax - dMin) > 0.01) {
                        fb1 = ((fb - dMin) / (dMax - dMin) * 9.0 + 1.0) * ratio;
                    } else {
                        fb1 = fb > 0 ? 10.0 * ratio : 0;
                    }
                    pScore.getScoreItem()[15] = fb1 > 0 ? fb1 : 0.0;
                    pScore.setTotal(pScore.getTotal() + pScore.getScoreItem()[15]);
                }
            }
        }
    }

    private boolean recheckCanSend_QuanBuZaiKu(Score s) {
        String why = "";
        if (0 == Integer.parseInt(SchData.hParamSet.get("AllInLibOnlyHaveDone").getParamDefaultValue())) {
            return true;
        }
        //如果是做过这个工序的，检查一下现在做做的是不是也是全部在库的，如果是，不可以发
        if (s.getPOp().getMScheduling().getMisHaveDonePos().contains(s.getPositionId())) {
            OrderProcess pOpTemp = preScheduling.getProcessWorkingByPosition(s.getPositionId());
            if (pOpTemp == null) {
                why = "全部在库只做做过判断，做过且当前没有正在做的工序，可以发；";
                s.setRemark(s.getRemark() + why);
                return true;
            } else {
                if (isAllUndoInLibAndFew(pOpTemp.getOrderProcessId())) {
                    why = "全部在库只做做过判断，做过但是当前正在做的工序也是全部在库的，不可以切换；";
                    s.setRemark(s.getRemark() + why);
                    return false;
                } else {
                    why = "全部在库只做做过判断，做过且当前正在做的工序不是全部在库，可以发；";
                    s.setRemark(s.getRemark() + why);
                    return true;
                }
            }
        } else {
            if (s.getPOp().getMScheduling().getMisHaveDonePos().isEmpty()) {
                why = "全部在库只做做过判断，没有人做过这个工序，可以发；";
                s.setRemark(s.getRemark() + why);
                return true;
            }
            if (s.getPOp().getMScheduling().getMisHaveDonePos().size() <
                    (s.getPOp().getMScheduling().getMisWorkingPos().size() + s.getPOp().getMScheduling().getMIncDecFlag())) {
                why = "全部在库只做做过判断，没有做过这个工序但是做过本工序的人数小于需要加到的人数，可以发；";
                s.setRemark(s.getRemark() + why);
                return true;
            }
            why = "全部在库只做做过判断，没有做过,有人做过，用做过的人来加人足够，不可以发；";
            s.setRemark(s.getRemark() + why);
            return false;
        }
        //why = "全部在库只做做过判断，未明，可以发；";
        //return true;
    }

    private boolean isAllUndoInLibAndFew(long miProcessId) {
        if (!isAllUndoInLib(miProcessId)) {
            return false;
        }
        OrderProcess pOp = cSchDataCollector.findProcessByID(miProcessId);
        if (pOp == null) return false;
        OrderDto order = SchData.orderId2Order.get(pOp.getMLocalOrderNum());
        List<SBoxData> boxes = order.getMCurBoxSetGroupByPart().get(pOp.getMPartId());
        int iKnowCnt = 0;
        int iBoxCnt = 0;
        for (SBoxData box : boxes) {
            if (box.getMiPartSeqNum() == pOp.getMiPartSeqNum()) {
                iKnowCnt += box.getMiPlanCnt();
            }
            if (box.getMiBoxStatus() == IN_LIB_B_S) {
                iBoxCnt++;
            }
        }
        int leftPiece = order.getMiTotalPlanCnt() - pOp.getMiFinishedCnt() - iKnowCnt;
        int paramBoxCnt = Integer.parseInt(SchData.hParamSet.get("MinInLibBoxPer").getParamDefaultValue());
        int ParamSTDcnt = Integer.parseInt(SchData.hParamSet.get("MinInLibSTDPer").getParamDefaultValue());
        if (iBoxCnt <= paramBoxCnt) {
            return true;
        }

        float totalInlibSecond = 0.0f;
        totalInlibSecond = pOp.getMfProcessTotalTime();
        totalInlibSecond *= iKnowCnt;
        return totalInlibSecond <= ParamSTDcnt;
    }

    private boolean recheckCanSend_WeiChi(Score s) {
        String why = "";
        //工位在产空可以换
        if (SchData.pPositionDtos.get(s.getPositionId()).getMiPosStatus() == FREE_P_S) {
            why = "当前维持判断，绝对空闲可以换；";
            s.setRemark(s.getRemark() + why);
            return true;
        }
        //找到工位当前在做的工序
        OrderProcess pOpTemp = preScheduling.getProcessWorkingByPosition(s.getPositionId());
        if (pOpTemp == null) {
            why = "当前维持判断，没有当前工序，可以换；";
            s.setRemark(s.getRemark() + why);
            return true;
        }
        if (pOpTemp.getOrderProcessId() == s.getPOp().getOrderProcessId()) {
            why = "当前维持判断，没有更换工序，可以继续做；";
            s.setRemark(s.getRemark() + why);
            return true;
        }

        boolean isLastNboxInLib = isAllUndoInLib(pOpTemp.getOrderProcessId());
        if (!isLastNboxInLib) {
            why = "当前维持判断，当前工序不是全部在库，可以换；";
            s.setRemark(s.getRemark() + why);
            return true;
        }
        int minStdPer = Integer.parseInt(SchData.hParamSet.get("MinInLibSTDPer").getParamDefaultValue());
        float stdInLib = pOpTemp.getMScheduling().getMBoxesInLib().getMiCutCnt();
        stdInLib *= pOpTemp.getMfProcessTotalTime();
        if (minStdPer > stdInLib) {
            why = "当前维持判断，当前工序是全部在库且总工时小于人均最小标准工时，不可以切换；";
            s.setRemark(s.getRemark() + why);
            return false;
        }
        why = "当前维持判断，当前工序是全部在库但总工时大于人均最小标准工时，可以切换；";
        s.setRemark(s.getRemark() + why);
        return true;
    }

    private boolean isAllUndoInLib(long miProcessId) {
        if (miProcessId == 0) return false;
        OrderProcess pOp = cSchDataCollector.findProcessByID(miProcessId);
        if (pOp == null) return false;

        OrderDto order = SchData.orderId2Order.get(pOp.getMLocalOrderNum());
        List<SBoxData> boxes = order.getMCurBoxSetGroupByPart().get(pOp.getMPartId());
        if (boxes == null) {
            boxes = Collections.emptyList();
        }
        int iKnowCnt = 0;
        for (SBoxData box : boxes) {
            if (box.getMiBoxStatus() == IN_LIB_B_S) {
                //如果在库
                if (box.getMUnDoneProcessID().contains(miProcessId)) {
                    if (!box.getMCanDoProcessSeq().contains(pOp.getMiPartSeqNum())) {
                        return false;
                    } else {
                        iKnowCnt += box.getMiPlanCnt();//在库但是可以做的件数
                    }
                }
            } else {
                // 如果不在库，未做的工序包含目标工序，而且当前工序不是目标工序，就说明有问题
                if (box.getMUnDoneProcessID().contains(miProcessId)) {
                    if (box.getMiPartSeqNum() != pOp.getMiPartSeqNum()) {
                        return false;
                    } else {
                        iKnowCnt += box.getMiPlanCnt();//不在库但是正在做的工序
                    }
                }
            }
        }
        gAllInLibUseTotal0Box1 = Integer.parseInt(SchData.hParamSet.get("AllInLibUseTotal0Box1").getParamDefaultValue());
        if (gAllInLibUseTotal0Box1 == 0) {
            OrderDto order1 = SchData.orderId2Order.get(pOp.getMLocalOrderNum());
            return (iKnowCnt + pOp.getMiFinishedCnt()) >= order1.getMiTotalPlanCnt();
        }
        return true;
    }

    private boolean reCheckCanSend_MinSTD(Score s) {
        String why = "";
        if (Integer.parseInt(SchData.hParamSet.get("ReCheckInLibStdPer").getParamDefaultValue()) == 0) {
            return true;
        }
        float stdInLib = s.getPOp().getMScheduling().getMBoxesInLib().getMiCutCnt();
        stdInLib *= s.getPOp().getMfProcessTotalTime();
        int workerPos = 0;
        int boxPerPosition = 0;
        workerPos = s.getPOp().getMScheduling().getMisWorkingPos().size() + 1;
        int gRuleMinStdtimeInLib = Integer.parseInt(SchData.hParamSet.get("MinInLibSTDPer").getParamDefaultValue());
        int gRuleMinBoxInLib = Integer.parseInt(SchData.hParamSet.get("MinInLibBoxPer").getParamDefaultValue());
        //最后n筐不考虑在库工时的条件还要加上当前没人在做这个工序，
        boxPerPosition = s.getPOp().getMScheduling().getMBoxesInLib().getMiBoxCnt() / workerPos;

        if((stdInLib / workerPos) >= gRuleMinStdtimeInLib) {
            return true;
        }
        if(boxPerPosition >= gRuleMinBoxInLib) {
            return true;
        }

        if (((stdInLib / workerPos) < gRuleMinStdtimeInLib) &&
                !s.getPOp().getMScheduling().getMisWorkingPos().isEmpty()) {
            if (SchData.pPositionDtos.get(s.getPositionId()).getMiPosStatus() == FREE_P_S) {
                //绝对空闲的时候可以选择发货
                if (s.getPOp().getMScheduling().getMisWorkingPos().isEmpty()) {
                    //当前没人在做，再检查有没有人做但是还没有回库
                    boolean Send2Other = false;
                    boolean Send2Me = false;
                    List<SBoxData> boxes = new ArrayList<>();
                    OrderDto order = SchData.orderId2Order.get(s.getPOp().getMLocalOrderNum());
                    if (order.getMCurBoxSetGroupByPart().containsKey(s.getPOp().getMPartId())) {
                        boxes = order.getMCurBoxSetGroupByPart().get(s.getPOp().getMPartId());
                    }
                    for (SBoxData pBox : boxes) {
                        if (pBox.getMiBoxStatus() == BACK_LIB_B_S || pBox.getMiBoxStatus() == SEND_PRO_B_S
                                || pBox.getMiBoxStatus() == WAITING_FOR_PRO_B_S || pBox.getMiBoxStatus() == IN_PRO_B_S) {
                            if (Long.parseLong(pBox.getMStatusInfo()) != s.getPositionId()) {
                                Send2Other = true;
                            } else {
                                Send2Me = true;
                            }
                        }
                    }
                    if (Send2Me) {
                        why = "在库工时不足且不是最后n筐工序,没人正在做，自己做过且绝对空闲，刚刚做了本工序，可以继续发；";
                    } else if (s.getPOp().getMScheduling().getMisHaveDonePos().contains(s.getPositionId())) {
                        //自己做过，那当然可以再做了，但是也要看有没有人在做
                        if (!Send2Other) {
                            //别人真的没有做过，不是还没做完
                            why = "在库工时不足且不是最后n筐工序，自己做过且其他人没有正在做，可以发";
                        } else {
                            why = "在库工时不足且不是没有人在做的最后n筐工序，自己做过但是其他人正在做，不可以发；";
                            s.setRemark(s.getRemark() + why);
                            return false;
                        }
                    } else if (s.getPOp().getMScheduling().getMisHaveDonePos().isEmpty()) {
                        //没有别人做过，也可以做,且当前不在库的筐不是别人的
                        if (!Send2Other) {
                            //别人真的没有做过，不是还没做完
                            why = "在库工时不足且不是没有人在做的最后n筐工序，自己做过且其他人没做过也没正在做，可以发；";
                        } else {
                            why = "在库工时不足且不是没有人在做的最后n筐工序，自己没做过但是其他人正在做，不可以发；";
                            s.setRemark(s.getRemark() + why);
                            return false;//
                        }
                    } else {
                        why = "在库工时不足且不是没有人在做的最后n筐工序，自己没做过且其他人做过，不可以发；";
                        s.setRemark(s.getRemark() + why);
                        return false;//
                    }
                } else {
                    why = "在库工时不足且不是没有人在做的最后n筐工序，自己不是正在做且其他人正在做，不可以发；";
                    s.setRemark(s.getRemark() + why);
                    return false;//
                }
            } else {
                if (s.getPOp().getMScheduling().getMisWorkingPos().contains(s.getPositionId())) {
                    why = "在库工时不足且不是没有人在做的最后n筐工序，不是绝对空闲但自己正在做，可以继续发；";
                } else {
                    why = "在库工时不足且不是没有人在做的最后n筐工序，不是绝对空闲也不是自己正在做，不可以发；";
                    s.setRemark(s.getRemark() + why);
                    return false;
                }
            }
        }
        s.setRemark(s.getRemark() + why);
        return true;
    }
}
